package com.example.demo.service.impl;

import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.example.demo.enumeration.Campus;
import com.example.demo.enumeration.ItemCategory;
import com.example.demo.enumeration.ItemStatus;
import com.example.demo.enumeration.SortOrder;
import com.example.demo.mapper.*;
import com.example.demo.pojo.dto.AddCommentDTO;
import com.example.demo.pojo.dto.AddItemDTO;
import com.example.demo.pojo.dto.OpenSearchAddItemDTO;
import com.example.demo.pojo.dto.UpdateItemDTO;
import com.example.demo.pojo.entity.Comment;
import com.example.demo.pojo.entity.Item;
import com.example.demo.pojo.properties.AliyunOpenSearchProperties;
import com.example.demo.pojo.vo.*;
import com.example.demo.service.ItemService;
import com.example.demo.service.UserService;
import com.example.demo.utils.AliyunOpenSearchUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
public class ItemServiceImpl implements ItemService {
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private ItemImageMapper itemImageMapper;
    @Autowired
    private CampusMapper campusMapper;
    @Autowired
    private ViewHistoryMapper viewHistoryMapper;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private CommentImageMapper commentImageMapper;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private UserService userService;

    /* 阿里云OpenSearch续费太贵，暂时停用
    @Autowired
    private AliyunOpenSearchProperties aliyunOpenSearchProperties;
    */

    private boolean addCampus(List<Campus> campuses, Long itemId) {
        for (Campus campus :
                campuses) {
            boolean result = campusMapper.addCampus(itemId, campus);
            if (!result) {
                return false;
            }
        }

        return true;
    }

    private boolean addImage(List<String> images, Long itemId) {
        for (String url :
                images) {
            boolean imageResult = itemImageMapper.addImage(itemId, url);
            if (!imageResult) {
                return false;
            }
        }

        return true;
    }

    private boolean addCommentImage(List<String> images, Long commentId) {
        for (String url :
                images) {
            boolean imageResult = commentImageMapper.addCommentImage(commentId, url);
            if (!imageResult) {
                return false;
            }
        }

        return true;
    }

    @Override
    @Transactional
    public boolean addItem(AddItemDTO addItemDTO) {
        Item item = new Item();

        BeanUtils.copyProperties(addItemDTO, item);

        Long currentUserId = userService.getCurrentUserId();
        item.setUserId(currentUserId);

        boolean itemResult = itemMapper.addItem(item);
        if (!itemResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        
        Long itemId = item.getId();
        List<Campus> campuses = addItemDTO.getCampuses();

        boolean campusResult = addCampus(campuses, itemId);
        if (!campusResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        boolean imageResult = addImage(addItemDTO.getImages(), itemId);
        if (!imageResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        /* 向阿里云OpenSearch新增数据，OpenSearch续费太贵，暂时停用
        OpenSearchAddItemDTO openSearchAddItemDTO = new OpenSearchAddItemDTO();

        BeanUtils.copyProperties(item, openSearchAddItemDTO);
        openSearchAddItemDTO.setCampuses(campuses);

        try {
            boolean result = AliyunOpenSearchUtil.addItem(aliyunOpenSearchProperties, openSearchAddItemDTO);

            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }

        } catch (OpenSearchClientException | OpenSearchException exception) {
            exception.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        */

        return true;
    }

    @Override
    public ItemDetailVO getDetail(Long id) {
        Item item = itemMapper.selectItemById(id);

        if (item == null) {
            return null;
        }

        ItemDetailVO itemDetailVO = new ItemDetailVO();

        BeanUtils.copyProperties(item, itemDetailVO);

        List<String> images = itemImageMapper.selectImageUrlByItemId(id);
        itemDetailVO.setImages(images);

        List<Campus> campuses = campusMapper.selectCampusByItemId(id);
        itemDetailVO.setCampuses(campuses);

        Long currentUserId = userService.getCurrentUserId();

        Long viewHistoryId = viewHistoryMapper.selectIdByIds(currentUserId, id);
        if (viewHistoryId == null) {
            viewHistoryMapper.addViewHistory(currentUserId, id);
        } else {
            viewHistoryMapper.updateTimeById(viewHistoryId);
        }

        return itemDetailVO;
    }

    @Override
    public Long selectUserIdByItemId(Long itemId) {
        return itemMapper.selectUserIdById(itemId);
    }

    @Override
    public ItemStatus selectStatusByItemId(Long itemId) {
        return itemMapper.selectStatusById(itemId);
    }

    @Override
    @Transactional
    public boolean updateItem(UpdateItemDTO updateItemDTO) {
        Item item = new Item();

        BeanUtils.copyProperties(updateItemDTO, item);

        boolean result = itemMapper.updateItem(item);
        if (!result) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        Long itemId = updateItemDTO.getId();

        boolean deleteCampus = campusMapper.deleteCampusByItemId(itemId);
        if (!deleteCampus) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        List<Campus> campuses = updateItemDTO.getCampuses();

        boolean campusResult = addCampus(campuses, itemId);
        if (!campusResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        /* 在阿里云OpenSearch更改数据，OpenSearch续费太贵，暂时停用
        try {
            boolean updateResult = AliyunOpenSearchUtil.updateItemInfo(aliyunOpenSearchProperties, updateItemDTO);
            if (!updateResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        } catch (OpenSearchClientException | OpenSearchException exception) {
            exception.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        */

        return true;
    }

    @Override
    @Transactional
    public boolean updatePrice(Long id, BigDecimal price) {
        boolean updateResult = itemMapper.updatePriceById(id, price);
        if (!updateResult) {
            return false;
        }

        /* 在阿里云OpenSearch更改数据，OpenSearch续费太贵，暂时停用
        try {
            boolean result = AliyunOpenSearchUtil.updateItemPrice(aliyunOpenSearchProperties, id, price);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        } catch (OpenSearchClientException | OpenSearchException exception) {
            exception.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        */

        return true;
    }

    @Override
    @Transactional
    public boolean updateImages(Long id, List<String> urls) {
        boolean deleteResult = itemImageMapper.deleteImage(id);
        if (!deleteResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        boolean imageResult = addImage(urls, id);
        if (!imageResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        boolean statusResult = itemMapper.updateStatusById(id, ItemStatus.pending);
        if (!statusResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        /* 在阿里云OpenSearch更改数据，OpenSearch续费太贵，暂时停用
        try {
            boolean result = AliyunOpenSearchUtil.updateItemStatus(aliyunOpenSearchProperties, id, ItemStatus.pending);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        } catch (OpenSearchClientException | OpenSearchException exception) {
            exception.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        */

        return true;
    }

    @Override
    @Transactional
    public boolean deleteItem(Long itemId) {
        boolean itemResult = itemMapper.deleteItemById(itemId);
        if (!itemResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        boolean campusResult = campusMapper.deleteCampusByItemId(itemId);
        if (!campusResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        boolean imageResult = itemImageMapper.deleteImage(itemId);
        if (!imageResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        List<Long> commentIdList = commentMapper.selectIdListByItemId(itemId);

        for (int i = 0; i < commentIdList.size(); i++) {
            Long commentId = commentIdList.get(i);

            List<String> images = commentImageMapper.selectCommentImagesByCommentId(commentId);
            if (images.size() != 0) {
                boolean result = commentImageMapper.deleteCommentImage(commentId);
                if (!result) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }

            List<Long> reports = reportMapper.selectIdListByCommentId(commentId);
            if (reports.size() != 0) {
                boolean result = reportMapper.deleteReportByCommentId(commentId);
                if (!result) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }
            }

        }

        if (commentIdList.size() != 0) {
            boolean result = commentMapper.deleteCommentByItemId(itemId);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }

        List<Long> reports = reportMapper.selectIdListByItemId(itemId);
        if (reports.size() != 0) {
            boolean result = reportMapper.deleteReportByItemId(itemId);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }

        viewHistoryMapper.deleteViewHistoryByItemId(itemId);

        /* 在阿里云OpenSearch删除数据，OpenSearch续费太贵，暂时停用
        try {
            boolean result = AliyunOpenSearchUtil.deleteItem(aliyunOpenSearchProperties, itemId);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        } catch (OpenSearchClientException | OpenSearchException e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        */

        return true;
    }

    @Override
    public PageVO searchItem(int page, String keyword, ItemCategory category, Campus campus, BigDecimal minPrice, BigDecimal maxPrice, SortOrder sortByPrice) {
        PageHelper.startPage(page, 16);
        Page<ItemListVO> data = itemMapper.searchItem(keyword, category, campus, minPrice, maxPrice, sortByPrice);

        long total = data.getTotal();
        List<ItemListVO> list = data.getResult();

        for (int i = 0; i < list.size(); i++) {
            ItemListVO itemListVO = list.get(i);

            Long itemId = itemListVO.getId();
            List<Campus> campuses = campusMapper.selectCampusByItemId(itemId);

            itemListVO.setCampuses(campuses);
        }

        return new PageVO(total, list);
    }

    @Override
    public List<ItemListVO> getCurrentItemList() {
        Long currentUserId = userService.getCurrentUserId();

        List<ItemListVO> list = itemMapper.getCurrentItemList(currentUserId);

        for (int i = 0; i < list.size(); i++) {
            ItemListVO itemListVO = list.get(i);

            Long itemId = itemListVO.getId();
            List<Campus> campuses = campusMapper.selectCampusByItemId(itemId);

            itemListVO.setCampuses(campuses);
        }

        return list;
    }

    @Override
    public List<ItemListVO> getItemListByUserId(Long userId) {
        Long currentUserId = userService.getCurrentUserId();

        List<ItemListVO> list;

        if (currentUserId.equals(userId)) {
            list = itemMapper.getCurrentItemList(currentUserId);
        } else {
            list = itemMapper.selectItemListByUserId(userId);
        }

        for (int i = 0; i < list.size(); i++) {
            ItemListVO itemListVO = list.get(i);

            Long itemId = itemListVO.getId();
            List<Campus> campuses = campusMapper.selectCampusByItemId(itemId);

            itemListVO.setCampuses(campuses);
        }

        return list;
    }

    @Override
    public List<ItemListVO> getItemListByIdList(List<Long> idList) {

        List<ItemListVO> list = new ArrayList<>();

        for (Long id :
                idList) {
            ItemListVO itemListVO = itemMapper.selectItemListVOById(id);

            List<Campus> campuses = campusMapper.selectCampusByItemId(id);
            itemListVO.setCampuses(campuses);

            list.add(itemListVO);
        }

        return list;
    }

    @Override
    @Transactional
    public boolean addComment(AddCommentDTO addCommentDTO) {
        Comment comment = new Comment();

        BeanUtils.copyProperties(addCommentDTO, comment);

        Long currentUserId = userService.getCurrentUserId();

        comment.setFromId(currentUserId);

        boolean commentResult = commentMapper.addComment(comment);
        if (!commentResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        Long commentId = comment.getId();

        List<String> images = addCommentDTO.getImages();
        if (images != null) {
            boolean imageResult = addCommentImage(addCommentDTO.getImages(), commentId);
            if (!imageResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }

        return true;
    }

    @Override
    @Transactional
    public boolean deleteComment(Long commentId) {
        if (commentMapper.selectParentIdById(commentId) == null) {
            List<Long> idList = commentMapper.selectIdListByParentId(commentId);

            for (int i = 0; i < idList.size(); i++) {
                Long id = idList.get(i);
                boolean commentResult = commentMapper.deleteCommentById(id);
                if (!commentResult) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return false;
                }

                List<String> images = commentImageMapper.selectCommentImagesByCommentId(id);
                if (images.size() != 0) {
                    boolean imageResult = commentImageMapper.deleteCommentImage(id);
                    if (!imageResult) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return false;
                    }
                }

                List<Long> reports = reportMapper.selectIdListByCommentId(id);
                if (reports.size() != 0) {
                    boolean result = reportMapper.deleteReportByCommentId(id);
                    if (!result) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return false;
                    }
                }
            }
        }

        boolean commentResult = commentMapper.deleteCommentById(commentId);
        if (!commentResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

        List<String> images = commentImageMapper.selectCommentImagesByCommentId(commentId);
        if (images.size() != 0) {
            boolean imageResult = commentImageMapper.deleteCommentImage(commentId);
            if (!imageResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }

        List<Long> reports = reportMapper.selectIdListByCommentId(commentId);
        if (reports.size() != 0) {
            boolean result = reportMapper.deleteReportByCommentId(commentId);
            if (!result) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return false;
            }
        }

        return true;
    }

    @Override
    public Long selectUserIdByCommentId(Long commentId) {
        return commentMapper.selectUserIdById(commentId);
    }

    @Override
    public Long selectItemIdByCommentId(Long commentId) {
        return commentMapper.selectItemIdById(commentId);
    }

    @Override
    public Long selectParentIdByCommentId(Long commentId) {
        return commentMapper.selectParentIdById(commentId);
    }

    @Override
    public List<CommentVO> getItemCommentList(Long itemId) {
        List<Comment> commentList = commentMapper.selectCommentListByItemId(itemId);

        if (commentList == null) {
            return null;
        }

        List<CommentVO> list = new ArrayList<>();

        for (Comment comment :
                commentList) {
            CommentVO commentVO = new CommentVO();
            BeanUtils.copyProperties(comment, commentVO);

            Long commentId = comment.getId();
            List<String> images = commentImageMapper.selectCommentImagesByCommentId(commentId);
            commentVO.setImages(images);

            list.add(commentVO);
        }

        return list;
    }

    @Override
    public List<UserCommentVO> getCurrentCommentList() {
        Long currentUserId = userService.getCurrentUserId();

        List<Comment> commentList = commentMapper.selectCommentListByUserId(currentUserId);
        if (commentList == null) {
            return null;
        }

        List<UserCommentVO> list = new ArrayList<>();

        for (Comment comment :
                commentList) {
            UserCommentVO userCommentVO = new UserCommentVO();
            BeanUtils.copyProperties(comment, userCommentVO);

            Long commentId = comment.getId();
            List<String> images = commentImageMapper.selectCommentImagesByCommentId(commentId);
            userCommentVO.setImages(images);

            list.add(userCommentVO);
        }

        return list;
    }

    @Override
    public boolean reportItem(Long itemId, String reason, String image) {
        return reportMapper.addItemReport(itemId, reason, image);
    }

    @Override
    public boolean reportItemComment(Long commentId, String reason, String image) {
        return reportMapper.addCommentReport(commentId, reason, image);
    }
}
